from math import radians, cos, sin, asin, sqrt
from httpUtil import HttpUtil
from DateTimeUtil import DateTimeUtil
from mysqlUtil import MySqlUtil
from runTimeLogUtil import RunTimeLogUtil
http = HttpUtil("http://api1.zelfly.com/carManager/assist/analysis/")
dtu = DateTimeUtil()
mysql = MySqlUtil()
log = RunTimeLogUtil()


class Main():
    def __init__(self):
        self.car_team_product_Iddict = {}

    def getCarIotId(self):
        """
        获取项目车队和车辆信息
        @return: 包含项目车队车辆信息的dict
        """
        try:
            null = ''
            productDict = {}
            carIotPathDict = {}
            result = eval(http.get())
            if result!='':
                if result['code'] == 1:
                    product_result = result['result']
                    for product_id in product_result:
                        product = product_result[product_id]
                        product_site = product['site']
                        productDict[product_id] = {}
                        productDict[product_id]['site'] = product_site
                        teamList = product['team']
                        for team in teamList:
                            team_id = team['id']
                            carList = team['car']
                            for car in carList:
                                car_id = car['carId']
                                self.car_team_product_Iddict[car_id] = [car['teamId'], car['projectId']]
                                carIotPathDict[car_id] = f'car/{car_id}'
                        productDict[product_id]['carIotPathDict'] = carIotPathDict
                        carIotPathDict = {}
            return productDict
        except Exception as e:
            log.exceptFileLog(msg=e)
            return {}

    def getCarCoord(self, path, startTime, endTime):
        """
        获取车辆行驶经纬度信息
        @param path: 请求路径
        @param startTime: 数据开始时间
        @param endTime: 数据终止时间
        @return: 车辆经纬度list
        """
        try:
            false = False
            true = True
            params = {
                "Identifier": 'Longitude-Latitude',
                "StartTime": startTime,
                "PageSize": 10000,
                "Asc": 1,
                "EndTime": endTime
            }
            result = eval(http.get(path=path, params=params))
            if result != '':
                if result['code'] == 1:
                    result = result['result']
                    if (result['PropertyDataInfos']['PropertyDataInfo']==[]): return []
                    LatitudeList = result['PropertyDataInfos']['PropertyDataInfo'][0]['List']['PropertyInfo']
                    LongitudeList = result['PropertyDataInfos']['PropertyDataInfo'][1]['List']['PropertyInfo']
                    CoordList = []
                    for index in range(0, len(LatitudeList)):
                        Coord = {}
                        Coord['Latitude'] = LatitudeList[index]['Value']
                        Coord['Longitude'] = LongitudeList[index]['Value']
                        Coord['time'] = LongitudeList[index]['Time']
                        CoordList.append(Coord)
                        index = index + 1
                    if result['NextValid']:
                        startTime = result['NextTime']
                        CoordList = CoordList + self.getCarCoord(path, startTime, endTime)
                    else:
                        pass
                    return CoordList
                else:
                    return []
            else:
                return []
        except Exception as e:
            log.exceptFileLog(msg=e)
            return []

    def isWithinSite(self, productSiteList, carSite):
        """
        判断车辆是否在项目点
        @param productSiteList: 项目点经纬度列表
        @param carSite: 车辆所在经纬度
        @return: 返回车辆所在项目点id和类型
        """
        try:
            for productSites in productSiteList:
                productSiteId = productSites['id']
                productSiteType = productSites['type']
                ProductSiteScope = productSites['scope']
                productSite = {'Latitude': productSites['latitude'], 'Longitude': productSites['longitude']}
                if productSiteType == '1':  # 作业点
                    if self.geodistance(productSite, carSite) <= ProductSiteScope:
                        # print(self.geodistance(productSite, carSite))
                        # print(productSiteType)
                        return productSiteId, productSiteType
                    else:
                        # print(self.geodistance(productSite, carSite))
                        pass
                elif productSiteType == '2':  # 卸土点
                    if self.geodistance(productSite, carSite) <= ProductSiteScope:
                        # print(self.geodistance(productSite, carSite))
                        # print(productSiteType)
                        return productSiteId, productSiteType
                    else:
                        # print(self.geodistance(productSite, carSite))
                        pass
                else:
                    pass
            return False, False
        except Exception as e:
            log.exceptFileLog(msg=e)
            return False, False

    def geodistance(self, productSite, carSite):
        """
        计算两点间距离-m
        @param productSite: 项目点经纬度坐标
        @param carSite: 车辆经纬度坐标
        @return: 车辆与项目点间的距离
        """
        try:
            lng1 = float(productSite['Longitude'])
            lat1 = float(productSite['Latitude'])
            lng2 = float(carSite['Longitude'])
            lat2 = float(carSite['Latitude'])
            lng1, lat1, lng2, lat2 = map(radians, [lng1, lat1, lng2, lat2])
            dlon = lng2 - lng1
            dlat = lat2 - lat1
            a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2
            dis = 2 * asin(sqrt(a)) * 6371 * 1000
            return dis
        except Exception as e:
            log.exceptFileLog(msg=e)
            return 9999999

    def carCoordHandle(self, carCoordList, productCoord):
        """

        @param carCoordList: 车辆经纬度坐标list
        @param productCoord: 项目点经纬度坐标
        @return: 车辆运输次数， 车辆行驶路径列表， 车辆信息list，车俩在各路线运输次数
        """
        try:
            carCount = 0
            carStatus = 2  # {status:1,beginSite:1,endSite:0} 0作业中，1挖完土-卸土路上，-1卸土中，2卸完土-挖土路上
            carPathList = []
            carPathCount = []
            carPath = ''
            carPathCountDict = {}
            departureTime = 0
            arrivalTime = 0
            resultDict = {}  # {siteId: id, status: 1, time: int}  status 1进2出
            resultList = []
            nowSite = 0
            for carCoord in carCoordList:
                productId, productType = self.isWithinSite(productCoord, carCoord)
                if (productType == '1'):  # 判断该卡车是否已在装载工地
                    if carStatus == 0:
                        # print('当前车在作业点')
                        nowSite = productId
                    elif carStatus == 2:
                        # print('车刚刚进入作业点')
                        nowSite = productId
                        carStatus = 0  # 将该卡车状态赋值为空载
                        carPath = f'{productId}'  # 将车路径覆盖为当前作业点ID
                        resultDict = {'siteId': productId, 'status': 1, 'time': carCoord['time']}
                        resultList.append(resultDict)
                    elif carStatus == 1:
                        # print('车再次进入作业点')
                        nowSite = productId
                        carStatus = 0  # 将该卡车状态赋值为空载
                        carPath = f'{productId}'  # 将车路径覆盖为当前作业点ID
                        resultDict = {'siteId': productId, 'status': 1, 'time': carCoord['time']}
                        resultList.append(resultDict)
                    elif carStatus == -1:
                        # print('车从卸土点直接到作业区')
                        nowSite = productId
                        carStatus = 0  # 将该卡车状态赋值为空载
                        carPath = f'{productId}'  # 将车路径覆盖为当前作业点ID
                        resultDict = {'siteId': productId, 'status': 1, 'time': carCoord['time']}
                        resultList.append(resultDict)
                elif (not productType):  # 判断是否是离开工地,且未到卸货工地
                    if carStatus == 0:  # 判断该卡车是否是空载
                        carStatus = 1  # 将该卡车状态更新为重载
                        # print('车刚刚离开作业点')
                        departureTime = carCoord['time']
                        resultDict = {'siteId': nowSite, 'status': 2, 'time': carCoord['time']}
                        resultList.append(resultDict)
                    elif carStatus == 1:
                        pass
                        # print('车正驶向卸土点')
                    elif carStatus == -1:
                        # print('车刚刚离开卸土点')
                        carStatus = 2  # 将该卡车状态更新为重载
                        resultDict = {'siteId': nowSite, 'status': 2, 'time': carCoord['time']}
                        resultList.append(resultDict)
                    elif carStatus == 2:
                        pass
                        # print('车正驶向挖土点')
                elif (productType == '2'):  # 判断是否进入卸货工地
                    if carStatus == 1:  # 判断该卡车是否是重载
                        carCount = carCount + 1
                        carStatus = -1
                        carPath = carPath + f'->{productId}'  # 在车路径追加当前作业点ID
                        carPathDict = {'carPath': carPath, 'departureTime': departureTime, 'arrivalTime': carCoord['time']}
                        carPathList.append(carPathDict)
                        resultDict = {'siteId': productId, 'status': 1, 'time': carCoord['time']}
                        resultList.append(resultDict)
                        if carPath not in carPathCountDict:
                            # print("当前无记录")
                            carPathCountDict[carPath] = 1
                        else:
                            # print("当前有记录")
                            carPathCountDict[carPath] = carPathCountDict[carPath] + 1
                        # print('车进入卸货点')
                        nowSite = productId
                    elif carStatus == -1:
                        # print('当前车在卸货点')
                        nowSite = productId
                    elif carStatus == 0:
                        # print('车从作业点直接进入卸货点')
                        nowSite = productId
                        resultDict = {'siteId': productId, 'status': 1, 'time': carCoord['time']}
                        resultList.append(resultDict)
                        carStatus = -1
                        carCount = carCount + 1
                        carPath = carPath + f'->{productId}'  # 在车路径追加当前作业点ID
                        carPathList.append(carPath)
                    elif carStatus == 2:
                        # print('车再次进入卸货点')
                        nowSite = productId
                        carStatus = -1
                        resultDict = {'siteId': productId, 'status': 1, 'time': carCoord['time']}
                        resultList.append(resultDict)
                else:
                    pass
            return carCount, carPathList, resultList, carPathCountDict
        except Exception as e:
            log.exceptFileLog(msg=e)
            return 0, [], [], {}

    def getTimeStamp(self, date=''):
        """
        根据日期获取前一天的开始时间戳和结束时间戳-s
        @param date: 日期
        @return: 开始时间戳和结束时间戳
        """
        if date == '':
            date = dtu.timeStamp2date()
        beginTime = date + ' 00:00:00'
        beginTimeStamp = dtu.datetime2timeStamp(beginTime) - 86400
        endTime = date + ' 23:59:59'
        endTimeStamp = dtu.datetime2timeStamp(endTime) - 86400
        # print(beginTimeStamp, endTimeStamp)
        return beginTimeStamp, endTimeStamp

    def saveToResultPath(self, carId, carPathList, beginTimeStamp):
        """
        将 车辆行驶路线记录 存入数据库
        @param carId: 车辆id
        @param carPathList: 车辆路线list
        @param beginTimeStamp: 前一天的开始时间戳
        @return:
        """
        try:
            carId = int(carId)
            teamId = int(self.car_team_product_Iddict[carId][0])
            projectId = int(self.car_team_product_Iddict[carId][1])
            resultDict = {'carId': carId, 'teamId': teamId, 'projectId': projectId}
            for carPathDict in carPathList:
                # print(carPathDict)
                beginSite, endSite = carPathDict['carPath'].split('->')
                resultDict['beginSite'] = beginSite
                resultDict['endSite'] = endSite
                resultDict['departureTime'] = carPathDict['departureTime']
                resultDict['arrivalTime'] = carPathDict['arrivalTime']
                resultDict['time'] = beginTimeStamp
                # resultDict['time'] = dtu.datetime2timeStamp()

                table = 'record'
                keys = str(tuple(resultDict.keys())).replace("'", "")
                values = str(tuple(resultDict.values()))
                sql = f"insert into {table} {keys} values{values}"
                if mysql.insert(sql=sql) == 'success':
                    pass
                    # print('成功')
                else:
                    pass
                    # print('失败')
            return True
        except Exception as e:
            log.exceptFileLog(msg=e)

    def saveToResult(self, carId, resultList):
        """
        将 车辆进出项目点记录 存入数据库
        @param carId: 车辆id
        @param resultList: 车辆行驶记录list
        @return:
        """
        try:
            carId = int(carId)
            teamId = int(self.car_team_product_Iddict[carId][0])
            projectId = int(self.car_team_product_Iddict[carId][1])
            resultDict = {'carId': carId, 'teamId': teamId, 'projectId': projectId}
            for result in resultList:
                resultDict['siteId'] = result['siteId']
                resultDict['status'] = result['status']
                resultDict['time'] = result['time']
                resultDict['createTime'] = dtu.timeStamp2datetime(result['time']/1000)

                table = 'result'
                keys = str(tuple(resultDict.keys())).replace("'", "")
                values = str(tuple(resultDict.values()))
                sql = f"insert into {table} {keys} values{values}"
                if mysql.insert(sql=sql) == 'success':
                    pass
                    # print('成功')
                else:
                    pass
                    # print('失败')
        except Exception as e:
            log.exceptFileLog(msg=e)

    def saveToResultPathCount(self, carId, carPathCountDict):
        """
        将 车辆各路线行驶次数 存入数据库
        @param carId: 车辆id
        @param carPathCountDict: 车辆各路线行驶次数dict
        @return:
        """
        try:
            carId = int(carId)
            teamId = int(self.car_team_product_Iddict[carId][0])
            projectId = int(self.car_team_product_Iddict[carId][1])
            resultDict = {'carId': carId, 'teamId': teamId, 'projectId': projectId}
            for result in carPathCountDict:
                # print(result)
                # print(carPathCountDict[result])
                resultDict['carPath'] = result
                resultDict['count'] = carPathCountDict[result]
                resultDict['time'] = dtu.datetime2timeStamp()

                table = 'resultpathcount'
                keys = str(tuple(resultDict.keys())).replace("'", "")
                values = str(tuple(resultDict.values()))
                sql = f"insert into {table} {keys} values{values}"
                # print(sql)
                if mysql.insert(sql=sql) == 'success':
                    pass
                    # print('成功')
                else:
                    pass
                    # print('失败')
        except Exception as e:
            log.exceptFileLog(msg=e)

    def main(self):
        """
        函数入口
        @return:
        """
        productDict = self.getCarIotId()
        count = 0
        lineCount = 0
        for productId in productDict:
            carIotPathDict = productDict[productId]['carIotPathDict']
            site = productDict[productId]['site']
            for key in carIotPathDict:
                path = carIotPathDict[key]
                # print(path)
                beginTimeStamp, endTimeStamp = self.getTimeStamp('2020-12-15')
                # print(beginTimeStamp, endTimeStamp)
                CoordList = self.getCarCoord(path, startTime=beginTimeStamp * 1000, endTime=endTimeStamp * 1000+999)
                # print(CoordList)
                carCount, carPathList, resultList, carPathCountDict = self.carCoordHandle(CoordList, site)
                carId = path.split('/')[1]
                count = count + len(resultList)
                lineCount = lineCount + int(carCount)
                self.saveToResult(carId, resultList)
                self.saveToResultPath(carId, carPathList, beginTimeStamp)
                # self.saveToResultPathCount(carId, carPathCountDict)
        return [count, lineCount]

if __name__ == '__main__':
    main = Main()
    # productDict = main.getCarIotId()
    # count = 0
    # lineCount = 0
    # for productId in productDict:
    #     carIotPathDict = productDict[productId]['carIotPathDict']
    #     site = productDict[productId]['site']
    #     for key in carIotPathDict:
    #         path = carIotPathDict[key]
    #         print(path)
    #         beginTimeStamp, endTimeStamp = main.getTimeStamp()
    #         print(beginTimeStamp, endTimeStamp)
    #         CoordList = main.getCarCoord(path, startTime=beginTimeStamp*1000, endTime=endTimeStamp*1000+999)
    #         # print(CoordList)
    #         carCount, carPathList, resultList = main.carCoordHandle(CoordList, site)
    #         carId = path.split('/')[1]
    #         print(resultList)
    #         count = count + len(resultList)
    #         lineCount = lineCount + int(carCount)
    #         main.saveToResult(carId, resultList)
    #         main.saveToResultPath(carCount, carPathList)
    # print(count, lineCount)
    print(main.main())

